/*
 *  Copyright (c) 2015-2018 Jose Osvaldo Suarez Domingos
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 */

///////////////////////////////////////////////////////////////////////////////

#ifndef BIG_UINT_H
#define BIG_UINT_H

///////////////////////////////////////////////////////////////////////////////

#define USE_ASM
//#define NO_STL
//#define NO_THROW

///////////////////////////////////////////////////////////////////////////////

#if defined(NO_THROW) && \
    !defined(NO_STL)
#warning You defined NO_THROW macro but not NO_STL; \
you should also define NO_STL, since "stl" can throw exceptions.
#endif

///////////////////////////////////////////////////////////////////////////////

#if !defined(NO_STL)
#include <ostream>
#endif

#include <cstdio>
#include <cstring>
#include <cinttypes>

///////////////////////////////////////////////////////////////////////////////

namespace gueb
{

///////////////////////////////////////////////////////////////////////////////

//const unsigned int big_uint_dynamic = static_cast<unsigned int>(0);

///////////////////////////////////////////////////////////////////////////////

#if defined(USE_ASM)

#if defined(__GNUC__) && \
    (defined(__i386__) || \
     defined(__i486__) || \
     defined(__i586__) || \
     defined(__i686__) || \
     defined(__x86_64))
#define GUEB_x86
#if defined(__i386__) || \
    defined(__i486__) || \
    defined(__i586__) || \
    defined(__i686__)
#define GUEB_32_BITS
#else
#define GUEB_64_BITS
#endif
#endif

#if defined(__GNUC__) && \
    (defined(__ARMEL__) || \
     defined(__AARCH64EL__))
#define GUEB_ARM

#if defined(__ARMEL__)
#define GUEB_32_BITS
#else
#define GUEB_64_BITS
#endif
#endif

#endif

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

//Estos ficheros deben ser incluidos en este orden.
//"big_uint_x86_64" requiere "big_uint_ops.h".
//"big_uint_static" requiere "big_uint_ops.h".
//"big_uint_dynamic" requiere "big_uint_ops.h" y "big_uint_static".
#include "big_uint_ops.h"

#if defined(GUEB_x86) && defined(GUEB_32_BITS)
//#include "big_uint_x86.h"
#endif
    
#if defined(GUEB_x86) && defined(GUEB_64_BITS)
#include "big_uint_x86_64.h"
#endif

#if defined(GUEB_ARM) && defined(GUEB_32_BITS)
//#include "big_uint_arm32.h"
#endif

#if defined(GUEB_ARM) && defined(GUEB_64_BITS)
//#include "big_uint_arm64.h"
#endif

#include "big_uint_static.h"
//#include "big_uint_dynamic.h"

///////////////////////////////////////////////////////////////////////////////

#if !defined(NO_STL)
TEMPLATE_BIG_UINT
inline
std::ostream & operator <<(std::ostream & out,
                           const BIG_UINT & n)
{
    out << n.str();
    return out;
}
#endif

///////////////////////////////////////////////////////////////////////////////

}//end namespace gueb

///////////////////////////////////////////////////////////////////////////////

#endif
